package com.mt.api.util;

import java.text.SimpleDateFormat;
import java.util.Random;

/**
 * Created by plover on 2019/3/20.
 */
public class SequenceBuilder {
    private static long key_lastTimestamp = -1L;
    private long key_sequence = 1L;
    private long muliNum = 100L;
    private long sequenceMax = key_sequence * muliNum;
    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    public synchronized String builderPayNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "PN" + seq;
    }

    public synchronized String builderOrderNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "ON" + seq;
    }

    public synchronized String builderOrderBackNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "OB" + seq;
    }

    public synchronized String builderInstoreNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "IN" + seq;
    }

    public synchronized String builderProductNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "PN" + seq;
    }

    public synchronized String builderOutStoreNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "OS" + seq;
    }



    public synchronized String builderStockTakingNo() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "ST" + seq;
    }

    private static long version_lastTimestamp = -1L;
    private long sequenceBits = 4L;
    private long sequenceMask = -1L ^ (-1L << sequenceBits);
    private long workerIdShift = sequenceBits;
    private long version_sequence = 1L;

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }


    public String builderSkuCode() {
        long timestamp = timeGen();
        if (key_lastTimestamp == timestamp) {
            key_sequence = key_sequence + 1;
            if (key_sequence >= sequenceMax) {
                timestamp = tilNextMillis(key_lastTimestamp);
            }
        } else {
            key_sequence = 1L;
        }
        String seq = sdf.format(timestamp);
        seq = String.valueOf(Long.parseLong(seq) * muliNum + key_sequence);
        key_lastTimestamp = timestamp;
        return "SK" + seq;
    }

    private static Random nameNoRandom = new Random();
    public String builderDefaultNameNo() {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < 4; i++) {
            int no = nameNoRandom.nextInt(10);
            builder.append(no);
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        SequenceBuilder sequence = new SequenceBuilder();
    }
}
